

window.dom = {
    create1(tagName) {
        return document.createElement(tagName)//创建一个节点，标签
    },
    create2(string) {
        const container = document.createElement('template')//div比较特殊，不能容纳一些标签，如<td></td>template标签可以容纳任意元素，但是不能用chilren拿到元素
        container.innerHTML = string.trim()
        return container.content.firstChild //template获取孩子的方法
    },
    after(node, node2) {//node后面插入node2
        node.parentNode.insertBefore(node2, node.nextSibling)  //插入节点
    },//当next sibling没有时该怎么办呢？实验证明也是可以的
    before(node, node2) {//node前面插入node2
        node.parentNode.insertBefore(node2, node)
        //insertBefore(a,b)把a插到b的前面
    },
    append(parent, node) {//新增儿子
        parent.appendChild(node)
    },
    wrap(node, parent) {//新增父亲
        dom.before(node, parent)//先把爸爸放到儿子的前面，变成他的兄弟
        dom.append(parent, node)//再把儿子放进爸爸的子级里面

    },
    remove(node) {  //删除该节点
        node.parentNode.removeChild(node)
        // node.remove(node) //接口较新，有些可能不支持
        return node  //返回删除的节点，以便还可以引用删除的东西

    },
    empty(node) {
        const { childNodes } = node
        //const childNodes = node.childNodes
        const array = []
        //     for (i = 0; i < childNodes.length; i++) {
        //         dom.remove(childNodes[i])
        //         array.push(childNodes[i])
        //     } //删的过程中，chilNodes的长度是在实时变化的，所以不能用这种方法
        let x = node.firstChild
        while (x) {
            array.push(dom.remove(node.firstChild))
            x = node.firstChild
        }
        return array
    },
    attr(node,name,value){  //更改属性，比如title等
        if(arguments.length===3){  //如果有三个参数就写
            return node.setAttribute(name,value)  //setAttribute,本来就有的API
        }else if(arguments.length===2){  //如果只有两个参数就读取
            return node.getAttribute(name)  //需要返回读取的值
        }//重载：根据不同的参数个数写不同的代码 
    },
    text(node,string){//但是这样会将里面所有的内容都替换，包括其他的标签
        if(arguments.length===2){
            if('innerText' in node){
                node.innerText=string  //支持一些其他浏览器+ie
            }else{
                node.textContent=string //不支持ie
            } //这样保证所有浏览器都可以支持
            //这样的编程方法叫适配
        }else if(arguments.length===1){//如果只有一个参数就读取
            if('innerText' in node){
                return node.innerText  
            }else{
                return node.textContent 
            } 
        }
       
    },
    html(node,string){
        if(arguments.length===2){
            node.innerHTML=string
        }else if(arguments.length===1){
            return innerHTML
        }
    },
    style(node,name,value){
        if(arguments.length===3){
            //dom.style(div,'color','red')
            node.style[name]=value
        }else if(arguments.length===2){
            if (typeof name==='string'){
                //dom.style(div,'color') 是想读取属性
                return node.style[name]
            }else if(name instanceof Object){//如果name是Object的实例（如果name是对象）
                //dom.style(div,{color:'red'})
                for(let key in name){  //遍历这个对象
                    node.style[key]=name[key]
                }
            }
        }
    },
    class:{
        add(node,className){
            node.classList.add(className)
        },
        remove(node,className){
            node.classList.remove(className)
        },
        has(node,className){
            return node.classList.contains(className)
        }
    },
    on(node,eventName,fn){
        node.addEventListener(eventName,fn)  //添加监听事件
    },
    off(node,eventName,fn){
        node.removeEventListener(eventName,fn) //移除监听事件，fn需与监听事件的fn一致
    },
    find(selector,scope){  //scope范围，比如test里面的p标签
        return (scope||document).querySelectorAll(selector)  //如果有指定范围就在指定的scope里面找，如果没有就在document里面找
    },//返回的是一个数组
    parent(node){
        return node.parentNode
    },
    children(node){
        return node.children
    },
    siblings(node){
        return Array.from(node.parentNode.children).filter(n=>n!=node)//Array.from()将...转变成数组
        //filter(n=>n!=node)排除自己
    },
    next(node){
        let x=node.nextSibling
        while(x && x.nodeType===3){ //排除节点类型是文本的情况，3是文本，1是节点
            x=x.nextSibling
        }
        return x
    },
    previous(node){
        let x=node.previousSibling
        while(x && x.nodeType===3){
            x=x.previousSibling
        }
        return x
    },
    each(nodeList,fn){
        for(let i=0;i<nodeList.length;i++){
            fn.call(null,nodeList[i])  //传参，this没有为null，第一个参数是nodeList[i]
        }
    },
    index(node){
        const list=dom.children(node.parentNode)
        let i
        for(i=0;i<list.length;i++){
            if(list[i]===node){
                break
            }
        }
        return i
    }
}